/* Class Name: OOR_AFAssigned 
 * Author: Accenture
 * Requirement/Project Name: OOR
 * Requirement Description: Batch APEX to be called by a scheduler interface to Create aggregate Afrontier Order for a month per USER
 **/
Global class OOR_AFAssigned implements Database.Batchable<sObject>{
List<Account> accDetailList = new List<Account>();//List for storing details of account.
    public   String query;//Query String
Public Id AccountId {get; set;}
Public Id SecondaryOwner {get;set;}
global database.querylocator start(Database.BatchableContext BC){
      return Database.getQueryLocator(query);
    }
    //Execute method will store the User against their Accounts and will call the createAFAssignedOrders method 
    global void execute(Database.BatchableContext BC, List<sObject> scope){
    List<User> UserList = new List<User>();//To get the User List 
    Map<Id,User> UserMap = new Map<Id,User>();// Map for UserId and User SObject
    Set<Id> UserIds = new Set<Id>();//Set of User Ids
    Map<Id,List<Account>> AccUserMap = new Map<Id,List<Account>>();//Map for User Ids with their Account Lists
    Map<Id,List<Account>> AccUserMapPrimaryMC = new Map<Id,List<Account>>();
    Map<Id,List<Account>> AccUserMapSecondaryMC = new Map<Id,List<Account>>();
    ID SFAOORCustRecordTypeID = RecordTypeHelper.GetRecordTypeID('Account', 'Local OOR Customer');
            for(sObject s : scope){ 
                    User u = (User)s;    
                     UserList.add(u);
                     UserMap.put(u.Id,u);
            }
         //Aggregate accounts per Owner   
         for(Account acc:[Select Id,Owner.ISACTIVE,OwnerId,OOR_Secondary_Account_Owner__c,Recurring_Charge__c,Opportunity__c,Contract_Signature_Date__c,OOR_Previous_Recurring_Charges__c,Renewal_Date__c,Secondary_Owner__c from Account where Account_Status__c !=: 'Inactive' AND RecordtypeId =: SFAOORCustRecordTypeID AND Name != 'OOR AF Assigned Account' AND Owner.ISACTIVE = TRUE AND (OwnerId IN: UserMap.keySet() OR OOR_Secondary_Account_Owner__c IN: UserMap.keySet())]){
             accDetailList.add(acc);
            if(acc.OOR_Secondary_Account_Owner__c == NULL && UserMap.containsKey(acc.ownerId)){
             UserIds.add(acc.OwnerId);
             if(AccUserMap.containsKey(acc.ownerId)){
                 AccUserMap.get(acc.ownerId).add(acc);
             }
             else{
                
                 AccUserMap.put(acc.ownerId,new List<Account>{acc});
             }
            }
            else if(UserMap.containsKey(acc.ownerId) && acc.OOR_Secondary_Account_Owner__c != NULL){
                if(AccUserMapPrimaryMC.containsKey(acc.OwnerId)){
                 AccUserMapPrimaryMC.get(acc.OwnerId).add(acc);
             }
             else{
                
                 AccUserMapPrimaryMC.put(acc.OwnerId,new List<Account>{acc});
             }
            } 
            else if(UserMap.containsKey(acc.OOR_Secondary_Account_Owner__c) && acc.OOR_Secondary_Account_Owner__c != NULL){
                if(AccUserMapSecondaryMC.containsKey(acc.OOR_Secondary_Account_Owner__c)){
                 AccUserMapSecondaryMC.get(acc.OOR_Secondary_Account_Owner__c).add(acc);
             }
             else{
                
                 AccUserMapSecondaryMC.put(acc.OOR_Secondary_Account_Owner__c,new List<Account>{acc});
             }
            }
         }
         //Call the void method to create an Order under the account 'OOR AF Assigned Account' per month
         If(AccUserMap.size()>0){
             createAFAssignedOrders(AccUserMap,UserMap);
         }
         If(AccUserMapPrimaryMC.size()>0){
             createAFAssignedOrders(AccUserMapPrimaryMC,UserMap);
         }
         If(AccUserMapSecondaryMC.size()>0){
             createAFAssignedOrders(AccUserMapSecondaryMC,UserMap);
         }
            
    }
    //Creating Orders for all the Active users and the cumulative value from their account list
      Public void createAFAssignedOrders(Map<Id,List<Account>> UserAccountMap,Map<Id,User> UserMap){
          List<Opportunity> OpptyList = new List<Opportunity>();
          List<String> idList = New List<String>();
          List<AFAssignedOrderHistory__c> historyObjList = new List<AFAssignedOrderHistory__c>();
          ID SFAOORRenewalecordTypeID = RecordTypeHelper.GetRecordTypeID('Opportunity', 'SFA-OOR Renewals');
          User adminId=[Select Id from User where Alias='sadmin']; 
          for(Id users:UserAccountMap.keyset()){
          Double RCharge = 0;
          //loop through the Map and add all RCs and create an order
            for(integer i=0;i<UserAccountMap.get(users).size();i++){
                
                    if(UserAccountMap.get(users)[i].Recurring_Charge__c != NULL){
                        if(UserAccountMap.get(users)[i].OOR_Secondary_Account_Owner__c== NULL){
                            RCharge = RCharge+UserAccountMap.get(users)[i].Recurring_Charge__c;
                        }
                        else if((UserAccountMap.get(users)[i].OOR_Secondary_Account_Owner__c!= NULL)&&(UserAccountMap.get(users)[i].OOR_Secondary_Account_Owner__c!=UserAccountMap.get(users)[i].OwnerId))
                        {
                            Rcharge=RCharge+UserAccountMap.get(users)[i].Recurring_Charge__c/2;
                        }
                    }
                    
                    
                if(i==UserAccountMap.get(users).size()-1){
                     
                    Opportunity oppt = new Opportunity();
                    oppt.RecordTypeId = SFAOORRenewalecordTypeID;
                    oppt.Amount = RCharge;
                    oppt.AccountId = AccountId;
                    //ListViewIds__c adminId = ListViewIds__c.getInstance(); 
                    oppt.OwnerId=adminId.Id;
                    //oppt.ownerId = users;
                    oppt.Ext_Primary_Owner__c=users;
                    oppt.StageName = 'Completed';
                    oppt.Opportunity_Type__c = 'AF Assigned';
                    oppt.Revenue_mo__c = RCharge;
                    Date Today = Date.Today();
                    integer noOfDays;
                    integer month;
                        
                            month = Today.Month();
                            noOfDays=Date.daysInMonth(Today.year(),Today.Month());
                            
                    oppt.closeDate = Date.newInstance(Today.year(),month,noOfDays);
                    String myString1 = String.ValueOf(oppt.CloseDate);
                    String NameDate = myString1.Substring(0,10);
                    system.debug('@@@@@@@@'+NameDate+'   '+myString1+'       '+UserMap.get(users));
                    oppt.Name = 'OOR AF Assigned'+' '+UserMap.get(users).FirstName+' '+UserMap.get(users).LastName+' '+NameDate;
                    system.debug('#######'+oppt.Name+'    '+UserMap.get(users));
                    oppt.Opportunity_Amount__c = RCharge;
                    oppt.Projected_Close_Date__c = Date.newInstance(Today.year(),month,noOfDays);
                    oppt.SOLO_Order_State__c = 'C';
                    oppt.Order_Completion_Date__c = oppt.CloseDate;
                    oppt.SOLO_Submitted_Date__c = oppt.CloseDate;
                    oppt.Order_Date_SOLO__c = oppt.CloseDate;
                    oppt.SOLO_Contract_Date__c =  oppt.CloseDate;
                    oppt.Monthly_Amount__c = RCharge;
                    oppt.SOLO_Contract_Revenue_mo__c = RCharge;
                    //oppt.Secondary_Owner__c=SecondaryOwner;
                    //oppt.Secondary_Owner__c=UserAccountMap.get(users)[i].OOR_Secondary_Account_Owner__c;
                    oppt.SOLO_Prev_Monthly_Amt__c = 0;
                    oppt.SOLO_Manager_P_Owner__c = UserMap.get(users).Manager.FirstName+' '+UserMap.get(users).Manager.LastName;
                    oppt.SOLO_Office_P_Owner_Code__c = UserMap.get(users).SFA_Office__c;
                    OpptyList.add(oppt);
                    idList.add(oppt.accountId);
                     }              
            }
        }
        System.Debug('LIST SIZE'+OpptyList);
        if(OpptyList.size()>0){
            try{
                Insert OpptyList;
                //Loop for inserting history Records.
                for(Account tempAcc: accDetailList)
                {
                    AFAssignedOrderHistory__c historyObj = new AFAssignedOrderHistory__c();
                    historyObj.AccountName__c = tempAcc.Id;
                    historyObj.AccountOwner__c = tempAcc.OwnerId;
                    historyObj.AFAssignedOrderId__c = tempAcc.Opportunity__c;
                    historyObj.ContractSignatureDate__c = tempAcc.Contract_Signature_Date__c;
                    historyObj.PreviousRecurringCharges__c = tempAcc.OOR_Previous_Recurring_Charges__c;
                    historyObj.RecurringCharges__c = tempAcc.Recurring_Charge__c;
                    historyObj.RenewalDate__c = tempAcc.Renewal_Date__c;
                    historyObj.SecondaryOwner__c = tempAcc.OOR_Secondary_Account_Owner__c;
                    historyObjList.add(historyObj); 
                 }
              try
              {
                  insert historyObjList;
              }
              catch(DMLException e)
              {
                   system.debug('DMLException'+e);
              }   
            }
            Catch(DMLException e){
                
                system.debug('DMLException'+e);
            }
        }
  }
    global void finish(Database.BatchableContext BC){
    
    
    // Query the AsyncApexJob object to retrieve the current job's information.
    AsyncApexJob a =    [Select Id, Status, NumberOfErrors, JobItemsProcessed,
                        TotalJobItems, CreatedBy.Email
                        from AsyncApexJob where Id =
                        :BC.getJobId()];
    // Send an email to the Apex job's submitter notifying of job completion.
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {a.CreatedBy.Email};
        mail.setToAddresses(toAddresses);
        mail.setSubject('Apex Sharing Recalculation ' + a.Status);
        mail.setPlainTextBody
                        ('The batch Apex job processed ' + a.TotalJobItems +
                        ' batches with '+ a.NumberOfErrors + ' failures.');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
    
    
    
    }
    static testMethod void testAFAssigned() {
        List<User> Userlist = new List<User>();
        List<Profile> ps = [select id, name from Profile where name = 'System Administrator' limit 1];
         
        User standard = new User(alias = 'staeww', 
        email='test@atti.com', 
        emailencodingkey='UTF-8', Firstname = 'RRICANErrezssf',
        lastname='Testingqwqasa', languagelocalekey='en_US', 
        localesidkey='en_US', 
        profileid = ps[0].Id,
        SFA_Office__c= 'BLT', 
        timezonesidkey='America/Los_Angeles', 
        username='Shinnaprwwen@testorg.com');
        Userlist.add(standard);
        insert Standard;
        
        User standard1 = new User(alias = 'stand1', 
        email='test1@atti.com', 
        emailencodingkey='UTF-8', Firstname = 'HURRICANEiughkdjgk',
        lastname='Testingwwwqwq', languagelocalekey='en_US', 
        localesidkey='en_US', 
        profileid = ps[0].Id, 
        SFA_Office__c= 'BLT',
        managerId = Standard.Id,
        timezonesidkey='America/Los_Angeles', 
        username='Shinnapren@testorg.com');
        Userlist.add(standard1);
        
        insert Standard1;
          
        ID SFAOORCustRecordTypeIDtest = RecordTypeHelper.GetRecordTypeID('Account', 'Local OOR Customer');
        List<Account> Accounts = new List<Account>();
        Account a;
        a = new Account();
        a.Name = 'UnitTest';
        a.Phone = '2332322323';
        a.Account_Status__c = 'Active';
        a.RecordTypeId = SFAOORCustRecordTypeIDtest;
        a.ownerId = Standard1.Id;
        Accounts.add(a);
        insert Accounts;
        Account a1;
        a1 = new Account();
        a1.Name = 'OOR AF Assigned Account Tesing';
        a1.Account_Status__c = 'Active';
        a1.Phone = '3323233443';
        a1.RecordTypeId = SFAOORCustRecordTypeIDtest;
        //Accounts.add(a1);
        insert  a1;  
          //  acct = [Select Id from Account where Name =: 'OOR AF Assigned Account' limit 1];
         test.starttest();               
            OOR_AFAssigned job = new OOR_AFAssigned();
            job.query = 'Select FirstName,LastName,SFA_Office__c,Id,ManagerId,Manager.FirstName,Manager.LastName,UserRole.Name from User where SFA_Office__c != NULL AND FirstName Like \'HURRICANE%\'';
            job.AccountId = a1.Id;
            Database.executeBatch(job,1);
         test.stopTest();
    }
}